
/* <<< COPYRIGHT START >>>
 * Copyright 2006-Present OxygenSoftwareLibrary.com
 * Licensed under the GNU Lesser General Public License.
 * http://www.gnu.org/licenses/lgpl.html
 * 
 * @author: Ugorji Dick-Nwoke
 * <<< COPYRIGHT END >>>
 */


package oxygen.jython;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import java.util.regex.*;
import oxygen.util.StringUtils;

/*
We are in easy syntax if
- we split the line based on whitespace, and take the first element, and it has a .
- there is no bracket in the first element
- the second element, if available, does not start with a bracket 

If all are not true, then just return the same string ...

wl.connect system gumby1234 localhost:9001/console

Need a class to handle the easy syntax

- Example
  wl.help abc ==> wl.help('abc')

a = wl.connect system gumby1234 localhost:9001/console ==> wl.connect('system', 'gumby1234', 'localhost')
a=wl.connect $user $password 'localhost:9001/console' means 

Note that we only work with Strings and arguments ...
anything else will not work ... 

- if an arg is parseable to a Number (double or int), leave it as such
- if arg starts with $, then it is an already defined variable
- if arg is in quotes, then it is a single variable ... 

EZ syntax only works if all characters match
alphabets or numbers, . " $ 

[variablename=]single command
no new line, etc ... 

Note:
- do not use easy syntax on built in jython functions
- do not use easy syntax on jython keywords
- only use when directly calling your own simple functions
- it's a convenience feature

*/
public class OxyJythonSyntaxHandler {
  private String s0 = null;
  private String s1 = null;
  private boolean ranConvert = false;
  private boolean convertWorked = false;
  
  private static Pattern pattern = null;  
  private static Pattern pattern2 = null;
  private static Set keywords = null;
  
  static {
    try {
      String[] keywords0 = new String[]{
        "and", "del", "for", "is", "raise",    
        "assert", "elif", "from", "lambda", "return",  
        "break", "else", "global", "not", "try",      
        "class", "except", "if", "or", "while",    
        "continue", "exec", "import", "pass", "yield",   
        "def", "finally", "in", "print"};
      keywords = new HashSet(Arrays.asList(keywords0));
      
      String uptocomm = "([\\w\\s=]*" + "\\.[\\w\\.]+)";
      String brack = "[\\s]*\\(";
      String arg = "[\\s]*(" + 
        "\\$[\\w\\.]+" + "|" + 
        "\\\'[^\\'\\\n]*\\\'" + "|" +
        "\\\"[^\\\"\\\n]*\\\"" + "|" + 
        "[^\\s]+|\\s*" + 
        ")";
      //String notmatch2 = "import";
      //String notmatch3 = "from.*? import";
      //String notmatchkeywords = "(" + StringUtils.toString(keywords, "|") + ")";
      // print a = wl.connect a $b c
      // print wl connect a $b c
      // wl connect a $b c
      // can take up to 7 args

      //String regex = uptocomm + arg + arg + arg + arg + arg + arg + arg;
      //String notregex = "[\\s]*(" + uptocomm + brack + "|" +
      //  notmatch2 + "|" + notmatch3 + "|" + notmatchkeywords + ").+";
      String regex = uptocomm + arg + arg + arg + arg + arg + arg + arg;
      String notregex = "\\s*(" + uptocomm + brack + "|" + 
        StringUtils.toString(keywords, "\\s|") + "\\s).+";
      //System.out.println("notregex: " + notregex);
      pattern = Pattern.compile(regex);
      pattern2 = Pattern.compile(notregex);
    } catch(Exception exc) {
      exc.printStackTrace();
    }
  }
  
  public OxyJythonSyntaxHandler(String s) {
    s0 = s.trim();
    s1 = s0;
  }
  
  public String getJythonSyntax() {
    convert();
    return s1;
  }
      
  public boolean convert() {
    try {
      if(!ranConvert) {
        doConvert();
      }
    } catch(Exception exc) {
      //exc.printStackTrace();
    } finally {
      ranConvert = true;
    }
    return convertWorked;
  }
  
  private void doConvert() throws Exception {
    Matcher matcher = pattern2.matcher(s0);
    boolean isMatched = matcher.matches();
    //System.out.println("isMatched notregex: " + isMatched);
    if(isMatched) {
      return;
    }

    matcher = pattern.matcher(s0);
    isMatched = matcher.find();
    //System.out.println("isMatched regex: " + isMatched);
    if(!isMatched) {
      return;
    }
    
    StringBuffer buf = new StringBuffer();
    //System.out.println("result: " + result);
    int numgroups = matcher.groupCount();
    buf.append(matcher.group(1));
    buf.append("(");
    //boolean beforeArgs = false;
    for(int i = 2; i < numgroups; i++) {
      String s = matcher.group(i);
      if(isEmpty(s)) {
        //do nothing
      } else if(s.startsWith("'")) {
        buf.append(s).append(",");
      } else if(s.startsWith("\"")) {
        buf.append(s).append(",");
      } else if(s.startsWith("$")) {
        s = s.substring(1);
        buf.append(s).append(",");
      } else if(isNumber(s)) {
        buf.append(s).append(",");
      } else {
        buf.append("'").append(s).append("'").append(",");
      }
    }
    buf.append(")");
    convertWorked = true;
    s1 = buf.toString();
  }

  private boolean isEmpty(String s) {
    return (s == null || s.trim().length() == 0);
  }
  
  private boolean isNumber(String s) {
    try {
      Integer.parseInt(s);
      return true;
    } catch(Exception e) { }
    try {
      Double.parseDouble(s);
      return true;
    } catch(Exception e) { }
    return false;
  }

  public static void main(String[] args) throws Exception {
    args = new String[] {
      "print a = wl.connect a b c",
      "a = wl.connect a b c",
      "print wl.connect a b c",
      " wl.connect a b c",
      "print wl.connect t3://localhost:9001 system $wl.password ",
      "print wl.connect 't3://localhost:9001' system $wl.password \"a b c\" ' d e f '",
      "print wl.connect t3://localhost:9001 system $password 1",
      "sys.exit()",
      "print sys.exit()",
      ""
    };
    for(int i = 0; i < args.length; i++) {
      System.out.println("--------------------------");
      String arg = args[i];
      System.out.println("arg: " + arg);
      OxyJythonSyntaxHandler wljsh = new OxyJythonSyntaxHandler(arg);
      System.out.print(System.currentTimeMillis());
      boolean b = wljsh.convert();
      System.out.print(" ... " + System.currentTimeMillis());
      System.out.println(" ... convert worked: " + b);
      String s1 = wljsh.getJythonSyntax();
      System.out.println(s1);
    }
  }

}


